<?php
ArrowController::importModel("org.arrowplatform.model.ArrowDataSource");
ArrowController::importModel("org.arrowplatform.controls.forms.IArrowFormField");
class ArrowTree extends ArrowTagContainer implements IArrowFormField{

	private $root;
	private $dataSource;
	
	private $typesMap = array();
	private $defaultType = "";
	private $nodeDescriptors = null;
	

	/**
	 * @var ArrowCtrlToolbar
	 */
	private $toolbar;

	private $standardActions = array(
		array("id" => "create", "name"=> "Dodaj", "code" => '<a class="ctrl-action ctrl-action-create" href="">Dodaj</a>'),
		array("id" => "save", "name"=> "Edytuj"),
		array("id" => "delete", "name"=> "Usuń", "code" => '<a class="ctrl-action ctrl-action-delete" href="">Usuń</a>'),
		array("id" => "openAll", "name"=> "Rozwiń", "code" => '<a class="ctrl-action ctrl-action-tree-open" href="">&nbsp;</a>'),
	);

	public function configure(){
		$this->addProperties(array(
			"structureField" => "name",
			"root" => 1,
			"maxlevel" => 0,
			"model" => null,
			"showStandardActions" => 1,
			"addModelTemplate" => false,
			"editModelTemplate" => false,
			"editSize" => "800|600",
			"height" => 0,
			"multiSelect" => 0,
			"formName" => false,
			"accessModel" => false,
			"disableInit" => 0,
			"onSelect" => '',
			"inactive" => '#F00',
			"hidden" => '#AAA',
			"nodeDescriptors" => null,
		));
		/*TODO: ADD active_field hidden_field' */
		$this->addRequiredProperties(array("ctrlId", "model"));
		$this->addStateProperties(array("root","inactive","hidden"));

		$formTest = $this->getParent("ArrowForm");

	}
	public function init(){
		$res = ArrowController::$activeProject->getResources();
		$this->registerJsFile( $res->getResource("/js/jquery/tree/jquery.tree.js")->getRelativePath());
		$this->registerJsFile( $res->getResource("/js/jquery/tree/plugins/jquery.tree.cookie.js")->getRelativePath());
		//if($this->getProperty("multiselect"))		
		$this->registerJsFile( $res->getResource("/js/jquery/tree/plugins/jquery.tree.checkbox.js")->getRelativePath());
		$this->registerJsFile( $res->getResource("/js/jquery/tree/plugins/jquery.tree.contextmenu.js")->getRelativePath());
		
		$am = $this->getProperty("accessModel") ;
		if( $am != false ) {
			foreach( $this->standardActions as &$sa ) {
				$sa["id"] = $am.":".$sa["id"] ;
			}
		}
		//	FB::log( $this->standardActions);
		$this->toolbar = $this->addNode("ui", "toolbar", array("ctrlId" => self::CTRL_NAMESPACE."-tree-toolbar-".$this->getId()));

		if( $this->getProperty("formName") == false )
      $this->setProperty("formName", $this->getProperty("ctrlId"));
      
    $this->nodeDescriptors = $this->getProperty("nodeDescriptors");


		$model = $this->getProperty("model");

		if($this->getProperty("showStandardActions")){
			if(!$this->getProperty("editModelTemplate"))
			throw new ArrowCoreException(array("msg" => "[ArrowTableTree] \"editModelTemplate\" property needet for standard actions"));

			$editTemplate = ArrowTemplateLinker::getDefault()->generateTemplateLink(array("path" => $this->getProperty("editModelTemplate")));
			$am = AccessManager::getDefault();
			foreach($this->standardActions as $act){
				if( $am->check( $model, $act["id"], 1 ) ) {
					$size = explode("|", $this->getProperty("editSize"));
					if(strpos( $act["id"], "save" ) !== false  ){
						$action = $this->toolbar->addNode("ui","action", array(
				              "id" => $act["id"],
				              "name" => $act["name"],
				              "type" => "dialog",
                      "width" => $size[0],
                      "height" => $size[1],
				              "template" => $this->getProperty("editModelTemplate"),
				              "ctrl-connected" => $this->getParent("ArrowCtrlAjax")->getId() 
							  
						));
						$action->addNode("ui", "param", array("name" => "id", "value" => "#id#"));
						$action->init();
					}else{
						$this->toolbar->addNode("ui","action", array(
			              "id" => $act["id"],
			              "name" => $act["name"],
			              "type" => "html"
			            ))->setContentCode($act["code"]);
					}
				}
			}
		}
		$jsConf = array(
			"multiSelect" => $this->getProperty("multiSelect"), 
			"disableInit" => $this->getProperty("disableInit"),
	 		"model" => $model,
	 		"structureField"=>$this->getProperty("structureField"),
			"onSelect"=>$this->getProperty("onSelect")
		);
		
		$maps = $this->getChildren("ArrowMapTreeNode");
		$types = array();
		
		foreach($maps as $key => $type){
			$field = $type->getProperty("field");
			$name = $type->getProperty("name");
			$name = $name?$name:"Type".$key;
			if(empty($field)){
				$this->defaultType = $name;
			}else{
				$this->typesMap[$field][$type->getProperty("value")] = $name;
			}
			$types[$name] = $type->generateJsOptions(); 
		}
		$jsConf["types"] = $types;
		
		
		if($addModel = $this->getProperty("addModelTemplate")){
			$jsConf["addTemplate"] = ArrowTemplateLinker::getDefault()->generateTemplateLink(array( "path" => $addModel, "parentId" => "#key#", "_htmlAmp" => 0, "iframe" => 1 ));
			$jsConf["editSize"] = $this->getProperty("editSize");
		}
		
		$this->registerJs(get_class($this), dirname(__FILE__)."/ArrowTree.js", ".".self::CTRL_NAMESPACE.'-tree-'.$this->getId(), $jsConf);
		$this->dataSource = new ArrowDataSource( $model );

		$this->root = $this->dataSource->getModelInstance($this->getProperty("root"));
		if(!($this->root instanceof TreeNode))
		throw new ArrowCoreException(array("msg" => "ArrowTreeNode needs instance of TreeNode"));
	}
	
	public function getName(){
		return $this->getId();
	}

	public function generate(){

		$text = $this->addNode("form", "hidden", array("name" => $this->getProperty("formName")));

		$str = '<div class="'.self::CTRL_NAMESPACE.'-tree '.self::CTRL_NAMESPACE.'-tree-'.$this->getId().'">';
		$str.= $text->generate();
		if($this->getProperty("showStandardActions"))
		$str.= '<div class="ctrl-tree-toolbar">'.$this->toolbar->generate()."</div>";
		$height = $this->getProperty("height");
		$str.= '<div class="'.self::CTRL_NAMESPACE.'-tree-outher" '.(($height)?'style="height: '.$height.'px;"':'').' >';
		$str.= '<div class="'.self::CTRL_NAMESPACE.'-tree-inner">';

		$str.= $this->generateTreeHtml($this->root);

		$str.="</div>";
		$str.="</div>";
		$str.="<div style=\"clear:both;\"></div></div>";
		$ajax = $this->getParent("ArrowCtrlAjax");
		return $str;

	}

	public function generateBlockStart(){
		return $this->generate();
	}

	public function generateBlockEnd(){
		return "";
	}
	
	private function generateTreeHtml($node){
		$strField = $this->getProperty("structureField");
		$conf = ArrowOrmConfig::getClassConf(get_class($node));
		
		
		$idPrefix = "ctrl-".$this->getId()."-";
		$style="";
		//print_r($conf);
		/*$addFields = implode(",", $this->getTypesFields());
		if(!empty($addFields)) $addFields = ",".$addFields;
		$q = "select id,depth,{$strField}".(isset($node["active"])?",active":"")." ".$addFields." from {$conf["attr"]["table"]} where left_id > {$node["left_id"]} && right_id < {$node["right_id"]} order by left_id";
		$result = ArrowOrmSqlRouter::query($q);*/
		$result = $node->getAllChildren();
		
		$str = "<ul>";
		$type = $this->getType($node);
		if($type)
			$class = "";//" typed";
	
    	$name = $node[$strField];
			
		if(isset($this->nodeDescriptors[$node["id"]]["name"]))
      		$name = $this->nodeDescriptors[$node["id"]]["name"];
      
    	if(isset($this->nodeDescriptors[$node["id"]]["postix"]))
      		$name = $name." ".$this->nodeDescriptors[$node["id"]]["postfix"];
      
    	$description = "";
    	if(isset($this->nodeDescriptors[$node["id"]]["description"]))
      		$description = $this->nodeDescriptors[$node["id"]]["description"];
			
		$str.= "<li rel=\"".$type."\" id=\"".$idPrefix.$node["id"]."\" class=\"root open\" ><a href=\"".$node["id"]."\" {$style}  ><ins>&nbsp;</ins>".$name."</a>\n";
		$class="";
		$currDepth = (int) $node["depth"];
		//while($row = mysql_fetch_assoc($result)){
		foreach($result as $row) {
			if($row["depth"] > $currDepth){
				$str.= str_repeat("<ul>",$row["depth"] -  $currDepth);
				$currDepth = $row["depth"];
			}elseif($row["depth"] < $currDepth){
				$str.= str_repeat("</ul>", $currDepth - $row["depth"]);
				$currDepth = $row["depth"];
			}
			$type = $this->getType($row);
			
			if($type)
				$class= " typed";
			else
				$class="";
			
		$name = $row[$strField]; 
		if(isset($this->nodeDescriptors[$row["id"]]["name"]))
      		$name = $this->nodeDescriptors[$row["id"]]["name"];
      
    	if(isset($this->nodeDescriptors[$row["id"]]["postix"]))
      		$name = $name." ".$this->nodeDescriptors[$row["id"]]["postfix"];
      
    	$description = "";
    	if(isset($this->nodeDescriptors[$row["id"]]["description"]))
      		$description = $this->nodeDescriptors[$row["id"]]["description"];
			
			$str.= "<li rel=\"".$type."\" id=\"".$idPrefix.$row["id"]."\" class=\"".$class."\" ><a href=\"".$row["id"]."\" {$style} title=\"".$name."\" ><ins>&nbsp;</ins>".$name."<span style=\"display: none;\" >".$description."</span></a>\n";
		}
		$str.= "</ul></ul>";
		return $str;
	}
	
	protected function getTypesFields(){
		$fields = array();
		if(!empty($this->typesMap)){
			foreach($this->typesMap as $field => $val){
				$fields[] = $field;
			}
		}
		return $fields;
	}
	
	protected function getType($context){
		$type = "";
		if(!empty($this->typesMap)){
			
			foreach($this->typesMap as $field => $val){
				
				if(isset($this->typesMap[$field][$context[$field]]))
					$type = $this->typesMap[$field][$context[$field]];
			}
		}
		if(!$type && $this->defaultType)
			$type = $this->defaultType;
			
		return $type;
	}
	
	
	public function isCheckable(){return true;}
	public function validate( $proposedValue ){

	}

}
?>